package com.huaxin.device.common;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.QRCodeWriter;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.Base64;
import java.util.HashMap;
import java.util.Map;

public class BarcodeGenerator {

    /**
     * 生成一维条码（Code128）为 Base64 图片
     */
    public static String generateBarcodeBase64(String sn) throws Exception {
        int width = 300;
        int height = 100;
        String format = "PNG";

        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 1); // 白边间距

        BarcodeFormat formatType = BarcodeFormat.CODE_128; // 一维码
        BitMatrix bitMatrix = new MultiFormatWriter().encode(sn, formatType, width, height, hints);

        BufferedImage image = toBufferedImage(bitMatrix);
        return toBase64(image, format);
    }

    /**
     * 生成带 SN 文字的一维条码（Code128）为 Base64 图片
     */
    public static String generateBarcodeWithTextBase64(String sn) throws Exception {
        int barcodeWidth = 300;
        int barcodeHeight = 80;
        int textHeight = 30;
        int imageHeight = barcodeHeight + textHeight; // 总高度 = 条码 + 文字

        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 1);

        BitMatrix bitMatrix = new MultiFormatWriter().encode(sn, BarcodeFormat.CODE_128, barcodeWidth, barcodeHeight, hints);

        // 创建带文字的图片
        BufferedImage image = createBarcodeImageWithText(bitMatrix, sn, barcodeWidth, barcodeHeight, imageHeight);
        return toBase64(image, "PNG");
    }

    /**
     * 创建条码图片 + SN 文字
     */
    private static BufferedImage createBarcodeImageWithText(BitMatrix bitMatrix,
                                                            String sn,
                                                            int width,
                                                            int barcodeHeight,
                                                            int imageHeight) {
        BufferedImage image = new BufferedImage(width, imageHeight, BufferedImage.TYPE_INT_RGB);
        Graphics2D g = image.createGraphics();

        // --- 背景 ---
        g.setColor(Color.WHITE);
        g.fillRect(0, 0, width, imageHeight);

        // --- 绘制条码 ---
        g.setColor(Color.BLACK);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < barcodeHeight; y++) {
                if (bitMatrix.get(x, y)) {
                    g.fillRect(x, y, 1, 1);
                }
            }
        }

        // --- 绘制 SN 文字 ---
        g.setFont(new Font("Dialog", Font.BOLD, 18)); // 可选字体：SansSerif, Arial, Dialog
        FontMetrics fm = g.getFontMetrics();
        int textWidth = fm.stringWidth(sn);
        int x = (width - textWidth) / 2; // 居中
        int y = barcodeHeight + 20;      // 文字在条码下方
        g.drawString(sn, x, y);

        g.dispose(); // 重要：释放资源
        return image;
    }


    /**
     * 生成二维码（QR Code）为 Base64
     */
    public static String generateQRCodeBase64(String sn) throws Exception {
        int width = 200;
        int height = 200;
        String format = "PNG";

        QRCodeWriter writer = new QRCodeWriter();
        BitMatrix bitMatrix = writer.encode(sn, BarcodeFormat.QR_CODE, width, height);

        BufferedImage image = toBufferedImage(bitMatrix);
        return toBase64(image, format);
    }

    /**
     * 将 BitMatrix 转为 BufferedImage
     */
    private static BufferedImage toBufferedImage(BitMatrix bitMatrix) {
        int width = bitMatrix.getWidth();
        int height = bitMatrix.getHeight();
        BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
        for (int x = 0; x < width; x++) {
            for (int y = 0; y < height; y++) {
                image.setRGB(x, y, bitMatrix.get(x, y) ? 0xFF000000 : 0xFFFFFFFF);
            }
        }
        return image;
    }

    /**
     * 将 BufferedImage 转为 Base64 字符串
     */
    private static String toBase64(BufferedImage image, String format) throws IOException {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, format, baos);
        byte[] imageBytes = baos.toByteArray();
        return Base64.getEncoder().encodeToString(imageBytes);
    }

    /**
     * 保存条码到文件
     */
    public static void saveBarcodeToFile(String sn, String filePath) throws Exception {
        int width = 300;
        int height = 100;
        Map<EncodeHintType, Object> hints = new HashMap<>();
        hints.put(EncodeHintType.CHARACTER_SET, "UTF-8");
        hints.put(EncodeHintType.MARGIN, 1);

        BitMatrix bitMatrix = new MultiFormatWriter().encode(sn, BarcodeFormat.CODE_128, width, height, hints);
        BufferedImage image = toBufferedImage(bitMatrix);
        ImageIO.write(image, "PNG", new File(filePath));
    }

    /**
     * 从图片中读取条码内容（可选功能）
     */
    public static String readBarcodeFromImage(File imageFile) throws Exception {
        BufferedImage image = ImageIO.read(imageFile);
        LuminanceSource source = new BufferedImageLuminanceSource(image);
        Binarizer binarizer = new HybridBinarizer(source);
        BinaryBitmap binaryBitmap = new BinaryBitmap(binarizer);
        Result result = new MultiFormatReader().decode(binaryBitmap);
        return result.getText();
    }
}